package com.waves.spring.boot.run;

import lombok.SneakyThrows;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.boot.*;
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.annotation.*;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.ClassPathResource;

import java.util.Arrays;

/**
 * 2、12 执行 runner
 */
@Configuration
public class RunApplication12 {

    @SneakyThrows
    @SuppressWarnings("all")
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication();
        app.addInitializers(applicationContext -> System.out.println("执行初始化器增强..."));
        System.out.println(">>> 2. 封装启动 args");
        DefaultApplicationArguments arguments = new DefaultApplicationArguments(args);

        System.out.println(">>> 8. 创建容器");
        GenericApplicationContext context = createApplicationContext(WebApplicationType.SERVLET);

        System.out.println(">>> 9. 准备容器");
        for (ApplicationContextInitializer initializer : app.getInitializers()) {
            initializer.initialize(context);
        }

        System.out.println(">>> 10. 加载 Bean 定义");
        DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
        AnnotatedBeanDefinitionReader reader1 = new AnnotatedBeanDefinitionReader(beanFactory);
        XmlBeanDefinitionReader reader2 = new XmlBeanDefinitionReader(beanFactory);
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(beanFactory);

        reader1.register(Config1.class);
        reader2.loadBeanDefinitions(new ClassPathResource("xml/bean1.xml"));
        scanner.scan("com.waves.spring.boot.run");

        System.out.println(">>> 11. refresh 容器");
        context.refresh();

        System.out.println(">>> 12. 执行 runner");
        for (CommandLineRunner runner : context.getBeansOfType(CommandLineRunner.class).values()) {
            runner.run(args);
        }
        for (ApplicationRunner runner : context.getBeansOfType(ApplicationRunner.class).values()) {
            runner.run(arguments);
        }

    }

    @Bean
    public CommandLineRunner commandLineRunner() {
        return args -> System.out.println("commandLineRunner()..." + Arrays.toString(args));
    }

    @Bean
    public ApplicationRunner applicationRunner() {
        return args -> {
            // 获取原始参数
            System.out.println("applicationRunner()..." + Arrays.toString(args.getSourceArgs()));
            // 获取选项名称，参数中带有 `--` 的参数
            System.out.println(args.getOptionNames());
            // 获取选项值
            System.out.println(args.getOptionValues("server.port"));
            // 获取非选项参数
            System.out.println(args.getNonOptionArgs());
        };
    }

    private static GenericApplicationContext createApplicationContext(WebApplicationType type) {
        GenericApplicationContext context = null;
        switch (type) {
            case SERVLET:
                context = new AnnotationConfigServletWebServerApplicationContext();
                break;
            case REACTIVE:
                context = new AnnotationConfigReactiveWebServerApplicationContext();
                break;
            case NONE:
                context = new AnnotationConfigApplicationContext();
                break;
        }
        return context;
    }
}
